﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace crmbl.Azure.Globals
{
    public class EncryptionHelper
    {

        public static X509Certificate2 LoadCertificate(StoreName storeName, StoreLocation storeLocation, string certificateName)
        {
            X509Store store = new X509Store(storeName, storeLocation);

            try
            {
                store.Open(OpenFlags.ReadOnly);

                X509Certificate2Collection certificateCollection =
                    store.Certificates.Find(X509FindType.FindBySubjectName,
                                            certificateName, false);

                if (certificateCollection.Count > 0)
                {
                    //  We ignore if there is more than one matching cert, 
                    //  we just return the first one.
                    return certificateCollection[0];
                }
                else
                {
                    throw new ArgumentException("Certificate not found");
                }
            }
            finally
            {
                store.Close();
            }
        }

        public static byte[] Encrypt(byte[] plainData, bool fOAEP, X509Certificate2 certificate)
        {
            if (plainData == null)
            {
                throw new ArgumentNullException("plainData");
            }
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
            {
                // Note that we use the public key to encrypt
                provider.FromXmlString(GetPublicKey(certificate));

                return provider.Encrypt(plainData, fOAEP);
            }
        }

        public static byte[] Decrypt(byte[] encryptedData, bool fOAEP, X509Certificate2 certificate)
        {
            if (encryptedData == null)
            {
                throw new ArgumentNullException("encryptedData");
            }
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
            {
                // Note that we use the private key to decrypt
                provider.FromXmlString(GetXmlKeyPair(certificate));

                return provider.Decrypt(encryptedData, fOAEP);
            }
        }

        public static string GetPublicKey(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            return certificate.PublicKey.Key.ToXmlString(false);
        }

        public static string GetXmlKeyPair(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            if (!certificate.HasPrivateKey)
            {
                throw new ArgumentException("certificate does not have a private key");
            }
            else
            {
                return certificate.PrivateKey.ToXmlString(true);
            }
        }
    }
}
